package org.basis.algorithm.bitoperation;

/**
 * 位运算基础操作
 *
 * @author Mr_wenpan@163.com 2022/01/18 14:59
 */
public class BaseOperation {

    public static void main(String[] args) {

    }

    /**
     * 返回ab中最大的那一个
     */
    public static int compareTwoNum(int a, int b) {

        return 0;
    }

    /**
     * 求a+b的平均数
     */
    public static int getAverge(int a, int b) {

        return (a & b) + ((a ^ b) >> 1);
    }

    /**
     * 交换ab两个数的值（注意a和b的内存地址不能是同一个才能这么做）
     */
    public static void swap(int a, int b) {
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        System.out.println("a = " + a + " b = " + b);
    }

    /**
     * 判断a是否是2的幂（这里也就是用到了判断a的二进制表示时是否只有一个1）
     */
    public static boolean isPowerOf2(int a) {
        // 如果a的二进制表示只有1个1，那么 a - 1就会把原来的1后面0变为1，然后把原来1的位置变为0，与操作后就为0了
        return (a & (a - 1)) == 0;
    }

    /**
     * 判断a是否是4的幂
     */
    public static boolean isPowerOf4(int a) {
        // 如果是4的幂，首先要是2的幂（即二进制表示时只有一个1）
        boolean isPowerOf2 = (a & (a - 1)) == 0;
        // 并且这个1要出现在偶数位上，所以这里通过 & 0x55555555 后会将该值变为0，因为0x55555555数所有奇数位置上为1
        return isPowerOf2 && ((a & 0xaaaaaaaa) == 0);
    }

    /**
     * 判断n的二进制表示有多少个1（这里n必须以二进制形式输入）
     */
    public int hammingWeight(int n) {
        int res = 0;
        for (int i = 0; i < 32; i++) {
            // 从最后一个位置开始，如果该位置是1，那么相与后的结果一定不为0
            if ((n & (1 << i)) != 0) {
                res++;
            }
        }
        return res;
    }

    /**
     * 获取a的符号位
     */
    public static int sign(int a) {
        // a左移31位后就将符号位移动到最后一位了，再与上1则，如果符号位为1则返回1，如果符号位为0则返回0
        return (a >> 31) & 1;
    }

    /**
     * 转换0和1（请保证输入的a不是0就是1）
     */
    public static int flip(int a) {

        // 将0变为1，将1变为0
        return a ^ 1;
    }

    /**
     * 不用任何比较，获取a b中较大的那一个（注意溢出：如果a b 不同号，则c有可能溢出），这个方法只适用于ab同号的情况，不同号的情况可能会溢出
     * 其实就是将比较转换为位运算的互斥条件
     */
    public static int getMax1(int a, int b) {
        int c = a - b;
        // 获取到a的符号位(如果a是大于b的，那么sa是 1 ，反之则为 0)
        int sa = flip(sign(c));
        // sb应该和sa互斥
        int sb = flip(sa);

        return sa * a + sb * b;
    }

}
